﻿namespace OutLook.Model.Domains
{
    using System;
    using System.Xml.Serialization;
    using OutLook.Model.Infrastructure;

    /// <summary>
    /// TODO: Nastya
    /// </summary>
    [Serializable]
    public class Composition : IEquatable<Composition>, IAssignable
    {
        #region Constructors

        /// <summary>
        /// Initializes new default instance of Composition
        /// </summary>
        private Composition() : this(string.Empty, 0.0d) { }

        /// <summary>
        /// Initializes new instance of Composition
        /// </summary>
        /// <param name="element">Element name</param>
        /// <param name="percentage">Percentage in substance</param>
        private Composition(string element, double percentage)
        {
            Element = element;
            Percentage = percentage;
        }

        #endregion

        #region Properties

        /// <summary>
        /// The title of element
        /// </summary>
        public string Element { get; set; }

        /// <summary>
        /// The content of element in composition (in percents)
        /// </summary>
        public double Percentage { get; set; }

        #endregion

        #region Facroty Method

        /// <summary>
        /// Creates new instance of Composition
        /// </summary>
        /// <param name="element">Element name (Cann't be empty or null)</param>
        /// <param name="percentage">Percentage in substance</param>
        /// <returns>New instance of Composition</returns>
        /// <remarks>Can return NULL if was wrong input arguments</remarks>
        public static Composition Create(string element, double percentage)
        {
            if (element == null || element.Equals(string.Empty))
                return null;

            return new Composition(element, percentage);
        }

        #endregion

        #region IEquatable<Composition> Implementation

        /// <summary>
        /// Compares current Composition with another one
        /// </summary>
        /// <param name="other">Another Composition</param>
        /// <returns>True - If current Composition and another one are equal, otherwise -False</returns>
        public bool Equals(Composition other)
        {
            if (other == null)
                return false;

            if (Element.Equals(other.Element) && Percentage == other.Percentage)
                return true;

            return false;
        }

        #endregion

        #region IAssignable Implementation

        /// <summary>
        /// Assigns values of current Composition to the argument object
        /// </summary>
        /// <param name="obj">Object to assign to</param>
        /// <exception cref="ArgumentNullException">If object to assign to is nullable</exception>
        /// <exception cref="NotSupportedException">If object to assign to doesn't fit</exception>
        public void AssignTo(object obj)
        {
            if (obj == null)
                throw new ArgumentNullException();

            if (obj is Composition)
            {
                Composition composition = obj as Composition;
                composition.Percentage = Percentage;
                composition.Element = Element;

                return;
            }

            throw new NotSupportedException();
        }

        #endregion
    }
}
